package cn.iocoder.yudao.framework.web.controller.hello;

import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
import cn.iocoder.yudao.framework.crypto.annotation.ApiResponseEncrypt;
import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Nonnull;
import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.SpringVersion;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

/**
 * <pre>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 *  默认控制器
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * </pre>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @since 2024/11/19
 */
@Tag(name = "你好")
@Controller
@RestController
public class HelloController {
    @Value("${xianmin.info.kernel}")
    private String kernel;

    @GetMapping(value = "/")
    @PermitAll
    public CommonResult<String> index() {
        return success(demo());
    }

    @GetMapping(value = "/hello/world")
    @Operation(summary = "简单示例")
    @PermitAll
    public CommonResult<String> helloDemo() {
        return success(demo());
    }

    @GetMapping(value = "/hello/encrypt")
    @Operation(summary = "加密示例")
    @Parameter(name = "X-Secret-Key", in = ParameterIn.HEADER, required = true, example = "V8Cq/dkBw4zo/vD70PsH5MGBTw7b/mad10nZx3Icb+ZCRcm2GLQDkDpQkxjRylm5kc+P8RIoC32GcsH78qRoqHp8nnKAkazQeNRjRiE6iP9QDa7G1GfYFaz5L+1fwLCfz29jdbFwUmPhlCEzMpjq8n/qKXJO7AiTc6IzEyigCFw=")
    @ApiResponseEncrypt
    @PermitAll
    public CommonResult<String> encryptDemo() {
        return success(demo());
    }

    @Nonnull
    private String demo() {
        String framework = "Spring " + SpringVersion.getVersion() + " + " + kernel;
        String runtime = System.getProperty("java.vm.vendor") + " "
                         + System.getProperty("java.vm.name") + " "
                         + System.getProperty("java.vm.version");
        String port = SpringUtils.getProperty("local.server.port", "");
        if (StrUtil.isBlank(port)) {
            port = SpringUtils.getProperty("server.port", "8080");
        }
        return framework + " run on " + runtime + ", Listen port " + port;
    }

    @GetMapping(value = "/hello/signature")
    @Operation(summary = "签名示例")
    @Parameter(name = "appId", in = ParameterIn.HEADER, required = true, example = "test")
    @Parameter(name = "timestamp", in = ParameterIn.HEADER, required = true, example = "1717494535932")
    @Parameter(name = "nonce", in = ParameterIn.HEADER, required = true, example = "e7eb4265-885d-40eb-ace3-2ecfc34bd639")
    @Parameter(name = "sign", in = ParameterIn.HEADER, required = true, example = "01e1c3df4d93eafc862753641ebfc1637e70f853733684a139f8b630af5c84cd")
    @ApiSignature(timeout = 2, timeUnit = TimeUnit.MINUTES)
    @PermitAll
    public CommonResult<String> signatureDemo() {
        return success(demo()).setMsg("""
                1、签名算法
                ① 将请求头、请求体、请求参数，按照一定顺序排列，然后添加密钥，获得需要进行签名的字符串。
                其中，每个调用方 appId 对应一个唯一 appSecret，通过在 Redis 配置，它对应 key 为 api_signature_app 的 HASH 结构，hashKey 为 appId。
                ② 之后，通过 SHA256 进行加密，得到签名 sign。
                注意：第三方调用时，每次请求 Header 需要带上 appId、timestamp、nonce、sign 四个参数。
                为什么使用请求 Header 传参？是为了避免这四个参数在请求 QueryString、Request Body 可能重复的问题！
                2. 使用步骤
                ① 在需要使用的 xxx-biz 模块的 ，引入 yudao-spring-boot-starter-protection 依赖。
                ② 在 Redis 中添加 appId 及 appSecret 的配置。
                ③ 在 Controller 的方法上，添加 @ApiSignature 注解。
                """);
    }

    /**
     * @see org.springdoc.webmvc.ui.SwaggerWebMvcConfigurer#addResourceHandlers
     * @see org.springdoc.core.utils.Constants#SWAGGER_UI_PREFIX
     */
    @SuppressWarnings("JavadocReference")
    @SneakyThrows
    @GetMapping(value = {"/swagger", "/swagger/", "/doc.html"}, produces = MediaType.TEXT_HTML_VALUE)
    @PermitAll
    public void swaggerUI(HttpServletResponse response) {
        // HTML 请求模式下 Swagger 接口文档页默认跳转页面
        response.sendRedirect("swagger-ui/index.html");
    }

    @SneakyThrows
    @GetMapping(value = {"/public", "/public/", "/static", "/static/"}, produces = MediaType.TEXT_HTML_VALUE)
    @PermitAll
    public void staticResource(HttpServletResponse response) {
        // HTML 请求模式下请求静态资源默认跳转页面
        response.sendRedirect("public/index.html");
    }


}
